﻿// -----------------------------------------------------------------------
// <copyright file="BookSubscriptionViewModelCustomBinder.cs" company="EPAM Systems">
////Copyright (c) EPAM Systems, 2012. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

namespace MBOP.Website.CustomModelBinders
{
	#region Usings

	using System;
	using System.Globalization;
	using System.Reflection;
	using System.Web.Mvc;

	using MBOP.Core.Entities.Library;
	using MBOP.Website.ViewModels.Library;

	#endregion

	/// <summary>
	/// BookSubscriptionViewModel binder 
	/// which assigns data from requests and MBOPortal.Models.Library.BookSubscriptionViewModel.
	/// </summary>
	public class BookSubscriptionViewModelCustomBinder : DefaultModelBinder
	{
		#region Constants

		/// <summary>
		/// Represents person identity request parameter name.
		/// </summary>
		public const string REQUEST_PARAM_NAME_PERSON_ID = "personID";

		/// <summary>
		/// Represents subscription state request parameter name.
		/// </summary>
		public const string REQUEST_PARAM_NAME_SUBSCRIPTION_STATE = "state";

		/// <summary>
		/// Represents book id request parameter name.
		/// </summary>
		public const string REQUEST_PARAM_NAME_BOOK_ID = "bookID";

		/// <summary>
		/// Represents subscription set request parameter name.
		/// </summary>
		public const string REQUEST_PARAM_NAME_SUBSCRIPTION_SET = "subscriptionSet";

		/// <summary>
		/// Represents person property name.
		/// </summary>
		private const string PROPERTY_NAME_PERSON_LOGON_NAME = "PersonLogonName";

		/// <summary>
		/// Represents person property name.
		/// </summary>
		private const string PROPERTY_NAME_PERSON_ID = "PersonID";

		/// <summary>
		/// Represents date property name.
		/// </summary>
		private const string PROPERTY_NAME_DATE = "Date";

		/// <summary>
		/// Represents subscription state property name.
		/// </summary>
		private const string PROPERTY_NAME_SUBSCRIPTION_STATE = "SubscriptionState";

		/// <summary>
		/// Represents book id property name.
		/// </summary>
		private const string PROPERTY_NAME_BOOK_ID = "BookID";

		/// <summary>
		/// Represents subscription set property name.
		/// </summary>
		private const string PROPERTY_NAME_SUBSCRIPTION_SET = "SubscriptionSet";

		/// <summary>
		/// Represents id key for model error collection.
		/// </summary>
		private const string ERROR_KEY_ID = "IDError";

		/// <summary>
		/// Represents id error message.
		/// </summary>
		private const string ERROR_MESSAGE_ID = "Wrong book ID";

		#endregion

		#region Public Methods

		/// <summary>
		/// Assigns the request values and book subscription view model.
		/// </summary>
		/// <param name="controllerContext">Controller context, which processing the current request.</param>
		/// <param name="bindingContext">Binding context. which contains values of the current request.</param>
		/// <returns>The book subscription view model object representation.</returns>
		public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
		{
			object resultObj = base.BindModel(controllerContext,bindingContext);

			ValueProviderResult personIDResult = bindingContext.ValueProvider.GetValue(REQUEST_PARAM_NAME_PERSON_ID);

			PropertyInfo personIDProperty = bindingContext.ModelType.GetProperty(PROPERTY_NAME_PERSON_ID);

			if (personIDResult != null)
			{
				personIDProperty.SetValue(resultObj, personIDResult.AttemptedValue, null);
			}
			
			PropertyInfo dateProperty = bindingContext.ModelType.GetProperty(PROPERTY_NAME_DATE);

			if (dateProperty != null)
			{
				dateProperty.SetValue(resultObj, DateTime.Now, null);
			}

			ValueProviderResult subscriptionSetResult = bindingContext.ValueProvider.GetValue(REQUEST_PARAM_NAME_SUBSCRIPTION_SET);

			if (subscriptionSetResult != null)
			{
				PropertyInfo subscriptionSetProperty = bindingContext.ModelType.GetProperty(PROPERTY_NAME_SUBSCRIPTION_SET);

				subscriptionSetProperty.SetValue(resultObj, subscriptionSetResult.AttemptedValue, null);
			}

			ValueProviderResult result = bindingContext.ValueProvider.GetValue(REQUEST_PARAM_NAME_SUBSCRIPTION_STATE);

			object convertedState = result.ConvertTo(typeof(SubscribeState), CultureInfo.InvariantCulture);

			PropertyInfo subscriptionActionProperty = bindingContext.ModelType.GetProperty(PROPERTY_NAME_SUBSCRIPTION_STATE);

			if (convertedState != null)
			{
				SubscribeState currentState = (SubscribeState)convertedState;

				subscriptionActionProperty.SetValue(resultObj, currentState, null);
			}
			else
			{
				subscriptionActionProperty.SetValue(resultObj, SubscribeState.Stateless, null);
			}

			result = bindingContext.ValueProvider.GetValue(REQUEST_PARAM_NAME_BOOK_ID);

			if (result != null)
			{
				int id;

				if (int.TryParse(result.AttemptedValue, out id))
				{
					PropertyInfo idProperty = bindingContext.ModelType.GetProperty(PROPERTY_NAME_BOOK_ID);

					idProperty.SetValue(resultObj, id, null);
				}
				else
				{
					bindingContext.ModelState.AddModelError(ERROR_KEY_ID, new InvalidCastException(ERROR_MESSAGE_ID));
				}
			}

			return resultObj;
		}

		#endregion
	}
}